// Magic Software, Inc.
// http://www.magic-software.com
// Copyright (c) 2000, All Rights Reserved
//
// Source code from Magic Software is supplied under the terms of a license
// agreement and may not be copied or disclosed except in accordance with the
// terms of that agreement.  The various license agreements may be found at
// the Magic Software web site.  This file is subject to the license
//
// RESTRICTED USE SOURCE CODE
// http://www.magic-software.com/License/restricted.pdf

#ifndef MGCTERRAINBLOCK_H
#define MGCTERRAINBLOCK_H

#include "MgcVector3.h"
class MgcBox3;
class MgcCamera;
class MgcFrustum;
class MgcTerrainPage;
class MgcTerrainVertex;
class MgcVector2;


class MgcTerrainBlock
{
public:
    unsigned char GetX () const;
    unsigned char GetY () const;
    unsigned char GetStride () const;
    MgcReal GetDelta (int i) const;
    MgcReal GetDeltaMax () const;
    MgcReal GetDeltaL () const;
    MgcReal GetDeltaH () const;
    const MgcVector3& GetMin () const;
    const MgcVector3& GetMax () const;

    void SetEven (bool bSet);
    bool GetEven () const;
    void SetProcessed (bool bSet);
    bool GetProcessed () const;
    void SetVisible (bool bSet);
    bool GetVisible () const;
    void SetVisibilityTested (bool bSet);
    bool GetVisibilityTested () const;

    bool BitsSet () const;
    void ClearBits ();

    // creation of the quadtree
    void Initialize (MgcTerrainPage* pkPage, MgcTerrainBlock* pkBlock,
        unsigned short usBlock, unsigned char ucX, unsigned char ucY,
        unsigned char ucStride, bool bEven);

    // allows for changing the height data during runtime
    void UpdateBoundingBox (MgcTerrainPage* pkPage, MgcTerrainBlock* pkBlock,
        unsigned short usBlock, unsigned char ucStride);

    // test for intersection of page's bounding box and view frustum
    void TestIntersectFrustum (const MgcTerrainPage* pkPage,
        const MgcCamera* pkCamera);

    // distant terrain assumption
    void ComputeInterval (const MgcVector3& rkModelEye, MgcReal fTolerance);

    // close terrain assumption
    void ComputeInterval (const MgcVector3& rkModelDir,
        const MgcVector3& rkModelEye, MgcReal fTolerance, MgcVector2& rkLoc,
        MgcReal fSpacing);

    void SimplifyVertices (MgcTerrainPage* pkPage,
        const MgcVector3& rkModelEye, const MgcVector3& rkModelDir,
        MgcReal fTolerance, bool bCloseAssumption);

    void Disable (MgcTerrainPage* pkPage);

    // quadtree indexing
    static unsigned short GetParentIndex (unsigned short usChild);
    static unsigned short GetChildIndex (unsigned short usParent,
        unsigned short usIndex);
    static bool IsFirstChild (unsigned short usIndex);
    static bool IsSibling (unsigned short usIndex, unsigned short usTest);

protected:
    // bit flags for m_ucFlags
    enum
    {
        EVEN_PARITY       = 0x01,
        PROCESSED         = 0x02,
        VISIBLE           = 0x04,
        VISIBILITY_TESTED = 0x08,
        BITS_MASK         = 0x0E  // all but even parity bit
    };

    void GetVertex9 (unsigned short usSize, MgcTerrainVertex* pkVOrigin,
        MgcTerrainVertex* apkTVertex[9]);

    // separating axis tests used for determining intersection
    bool TestIntersect (const MgcBox3& rkBox, const MgcFrustum& rkFrustum);

    unsigned char m_ucX, m_ucY, m_ucStride, m_ucFlags;
    MgcReal m_fDelta[5], m_fDeltaMax;
    MgcReal m_fDeltaL, m_fDeltaH;
    MgcVector3 m_kMin, m_kMax;
};

#include "MgcTerrainBlock.inl"

#endif
